package com.bjsxt;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

/**TCP 一对多聊天服务器
 * 例如多个人访问同一个网站  聊天群*/
/*有一个公共的数据缓冲区  当客户发送消息时，数据发送到公共缓冲区，接
* 收消息的线程才启动，从公共缓冲区获取消息，再返回各个客户端*/
/*接收客户端发送消息的线程类*/
class ChartReceive  extends Thread{
    private Socket socket;
    //实例化时通过构造方法传进来
    public ChartReceive(Socket socket){
        this.socket=socket;
    }
    @Override
    public void run() {
        this.receive();
    }
    private void receive(){
        BufferedReader br = null;
        try{
            //用BufferedReader读取客户发来的消息  字节转字符
            //创建读取客户发来的消息的流的对象
            br = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
            while (true){
                String msg = br.readLine();
                //线程同步，多个线程访问同一个对象，
                //接收消息与发送消息互斥 所以用synchronized 对象锁是字符串
                synchronized ("aa"){
                    //将接收到的消息发送给公共缓冲区
                    ChartRoomServer02.buf = "["+this.socket.getInetAddress()+"]"+" "+msg;
                    //唤醒发送消息线程
                    "aa".notifyAll();
                }

            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if(br != null){
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(this.socket != null){
                try {
                    this.socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}
/*向客户端发送消息的线程类*/
class ChartSend  extends Thread{
    private Socket socket;
    //实例化时通过构造方法传进来
    public ChartSend(Socket socket){
        this.socket=socket;
    }
    @Override
    public void run() {
        this.send();
    }
    private void send(){
        PrintWriter pw = null;
        try {
            pw = new PrintWriter(this.socket.getOutputStream());
            while (true){
                synchronized ("aa") {
                    "aa".wait();
                    //将从公共数据区获得的消息发送出去
                    pw.println(ChartRoomServer02.buf);
                    pw.flush();
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if(this.socket != null){
                try {
                    this.socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(pw != null){
                pw.close();
            }
        }
    }
}
public class ChartRoomServer02 {
    //定义公共数据区  公共数据区是唯一的，在成员变量加static 是字符串类型
    public static String buf;
    public static void main(String[] args) {
        //主线程作用：建立与客户端持续连接
        System.out.println("Chat Server Version 1.0");
        System.out.println("Listen at 8888.....");
        ServerSocket serverSocket =null;
        try{
            serverSocket = new ServerSocket(6666);
            //不停地监听是否有新用户连接
            while (true){
                Socket socket = serverSocket.accept();
                System.out.println("连接到" + socket.getInetAddress());
                new ChartReceive(socket).start();
                new ChartSend(socket).start();
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if(serverSocket != null){
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}
